#include "HttpCmdSession.h"
#include "RobotUser.h"
#include "LogEx.h"
#include "BasicServerEx.h"
#include "CurlManager.h"
#include <json/json.h>
using namespace SGLib;
using namespace std;
#include "LoginMessage.pb.h"

extern IServerEx *gsvr;
string GAME_URL = "sg.dongdongnet.cn";

void loginGame(string &account, string &passwd);
void getServerList(string &account, u64 userid, string &sessionid);

static void onStart(const std::string &userdata)
{
    LOG_DEBUG("onStart");
}
static size_t onData(const std::string &userdata, void *ptr, size_t size, size_t nmemb)
{
    LOG_DEBUG("onData szie:%d nmemb:%d", size, nmemb);
    return 0;
}
static void timercall_LoginGame(void *pData, s32 nDataLen)
{
    if( nDataLen <= 0 )
    {
        LOG_ERROR("[%s]", __FUNCTION__);
        return;
    }

    string account((char*)pData, nDataLen);
    const char *passwd = CRobotUserManager::Instance().GetPasswd( account );
    LOG_DEBUG("[%s] account[%s][%s] try login game", __FUNCTION__, account.c_str(), passwd?passwd:"" );
    string strpass(passwd?passwd:"");
    loginGame( account, strpass );
}
static void timercall_GetServerList(void *pData, s32 nDataLen)
{
    if( nDataLen <= 0 )
    {
        LOG_ERROR("[%s]", __FUNCTION__);
        return;
    }

    string account((char*)pData, nDataLen);
    u64 userid = CRobotUserManager::Instance().GetUserId( account );
    string sessionid = CRobotUserManager::Instance().GetSessionId( account );
    LOG_DEBUG("[%s] account[%s] user[%llu][%s] try get serverlist", __FUNCTION__, 
        account.c_str(), userid, sessionid.c_str() );
    getServerList( account, userid, sessionid );
}
static void timercall_ConnectGameServer(void *pData, s32 nDataLen)
{
    if( nDataLen <= 0 )
    {
        LOG_ERROR("[%s]", __FUNCTION__);
        return;
    }

    string account((char*)pData, nDataLen);
    const char *ip = CRobotUserManager::Instance().GetIp( account );
    s32 port = CRobotUserManager::Instance().GetPort( account );
    u64 id = CRobotUserManager::Instance().GetId( account );
    if( ip )
    {
        UserData ud;
        ud.u64d = id;
        LOG_DEBUG("[%s] account[%s] id[%llu] connect game[%s:%d]", __FUNCTION__, 
            account.c_str(), id, ip, port );
        gsvr->Connect( 1, ip, port, &ud );
    }
    else
    {
        CRobotUserManager::Instance().DestoryRobot( account );
    }
}

static void onLoginEnd(const std::string &userdata, const std::string &rsp)
{
    // 找到真实数据位置
    const char *ptr = strstr( rsp.c_str(), "\r\n\r\n");
    ptr += 4;
    int left = rsp.size() - (ptr - rsp.c_str());
    LOG_DEBUG("[%s] account[%s] recvdatalen[%d] left[%d]", 
        __FUNCTION__, userdata.c_str(), rsp.size(), left);

    com::future::threekingdoms::server::transport::protocol::LoginRsp registerRsp;
    registerRsp.ParseFromArray(ptr, left);

    LOG_DEBUG("[%s] account[%s] loginresult[%d]",
        __FUNCTION__, userdata.c_str(), registerRsp.result());

    if(1 == registerRsp.result())
    {
        CRobotUserManager::Instance().UpdateRobot( userdata, registerRsp.userid(), registerRsp.sessionid() );
        // 登录成功 准备获取服务器列表
        s32 aftersec = 100;
        s32 tid = gsvr->AddTimer(aftersec, timercall_GetServerList, (void*)userdata.c_str(), userdata.length(), false);
        LOG_DEBUG( "[%s] account[%s] will get serverlist aftersec[%d] tid[%d]", __FUNCTION__,
            userdata.c_str(), aftersec, tid );
    }
    else
    {
        CRobotUserManager::Instance().DestoryRobot( userdata );
    }
}
void loginGame(string &account, string &passwd)
{
    std::string url = GAME_URL;
    url.append(":36666/login");

    com::future::threekingdoms::server::transport::protocol::LoginReq httpReq;
    httpReq.set_account(account);
    httpReq.set_authenticid(passwd);
    //useless element
    httpReq.set_accountnum(0);
    httpReq.set_accountpt("test");
    httpReq.set_imei(account);
    httpReq.set_ua(account);
    httpReq.set_channelid(com::future::threekingdoms::server::transport::protocol::LoginReq::QIANLIANG);
    httpReq.set_batchid(0);
    httpReq.set_recommendid(0);
    httpReq.set_systemversion("test");
    httpReq.set_nettype(0);
    httpReq.set_apkwithres(0);
    httpReq.set_platformuserid("test");

    string msgData;
    httpReq.SerializeToString(&msgData);

    LOG_DEBUG("[%s] account[%s]pass[%s] postlen:%d", __FUNCTION__, 
        account.c_str(), passwd.c_str(), msgData.size());
    CCurlManager::Instance().PostRequest4Data(url, msgData, onStart, onData, onLoginEnd, account);
}

static void onServerListEnd(const std::string &userdata, const std::string &rsp)
{
    // 找到真实数据位置
    const char *ptr = strstr( rsp.c_str(), "\r\n\r\n");
    ptr += 4;
    int left = rsp.size() - (ptr - rsp.c_str());
    LOG_DEBUG("[%s] account[%s] recvdatalen[%d] left[%d]", 
        __FUNCTION__, userdata.c_str(), rsp.size(), left);

    com::future::threekingdoms::server::transport::protocol::ServerListRsp pbrsp;
    pbrsp.ParseFromArray(ptr, left);

    LOG_DEBUG("response.result = %d", pbrsp.result());
    if(1 == pbrsp.result())
    {
        int sz = pbrsp.serverinfos_size();
        LOG_DEBUG("get server list success, serversz:%d", sz);
        for( int i=0; i<sz; ++i )
        {
            LOG_DEBUG("serverinfos[%d] roleid:%d", i, pbrsp.serverinfos(i).roleid());
            LOG_DEBUG("serverinfos[%d] has_roleid():%d", i, pbrsp.serverinfos(i).has_roleid());
            LOG_DEBUG("serverinfos[%d] addr[%s:%d]", i, pbrsp.serverinfos(i).ip().c_str(), pbrsp.serverinfos(i).port() );
            if( pbrsp.serverinfos(i).has_roleid() )
            {
                CRobotUserManager::Instance().UpdateRobot( userdata, pbrsp.serverinfos(i).roleid(),
                    pbrsp.serverinfos(i).ip(), pbrsp.serverinfos(i).port() );
            }
        }

        s32 aftersec = (rand() % 3 + 3) * 1000;
        s32 tid = gsvr->AddTimer(aftersec, timercall_ConnectGameServer, (void*)userdata.c_str(), userdata.length(), false);
        LOG_DEBUG( "[%s] account[%s] will connect gameserver aftersec[%d] tid[%d]", __FUNCTION__,
            userdata.c_str(), aftersec, tid );
    }
    else
    {
        CRobotUserManager::Instance().DestoryRobot( userdata );
    }
}
void getServerList(string &account, u64 userid, string &sessionid)
{
    std::string url = GAME_URL;
    url.append(":36666/serverlist");

    com::future::threekingdoms::server::transport::protocol::ServerListReq httpReq;
    httpReq.set_userid(userid);
    httpReq.set_sessionid(sessionid);

    string msgData;
    httpReq.SerializeToString(&msgData);

    LOG_DEBUG("[%s] [%s] user[%llu][%s] post datalen[%d]", __FUNCTION__,
        account.c_str(), userid, sessionid.c_str(), msgData.size());
    CCurlManager::Instance().PostRequest4Data(url, msgData, onStart, onData, onServerListEnd, account);
}


bool CHttpCmdSocket::OnRequest(CHttpRequest &request)
{
    LOG_DEBUG("OnRequest:body:%s", request.GetBody().c_str() );
    CHttpResponse rsp(200, "success");
    Reply(rsp);
    // 收到充值完成通知, 准备开始消耗
    try
    {
        Json::Reader reader;
        Json::Value root;
        if( reader.parse(request.GetBody().c_str(), root) )
        {
            string account = root["account"].asString();
            string passwd = root["passwd"].asString();
            int recharge = root["recharge"].asInt();

            bool hasfound = CRobotUserManager::Instance().HasRobot( account );
            if( hasfound )
            {
                // 当前帐号已经存在了 只需要更新充值金额即可
                CRobotUserManager::Instance().UpdateRobot( account, recharge );
            }
            else
            {
                // 当前不存在 准备使用帐号登录游戏
                CRobotUserManager::Instance().CreateRobot( account, passwd, recharge );
                s32 aftersec = (rand() % 5 + 5) * 1000;
                s32 tid = gsvr->AddTimer(aftersec, timercall_LoginGame, (void*)account.c_str(), account.length(), false);
                LOG_DEBUG( "[%s] account[%s]passwd[%s] will logingame aftersec[%d] tid[%d]", __FUNCTION__,
                        account.c_str(), passwd.c_str(), aftersec, tid );
            }
        }
    }
    catch( ... )
    {
    }

    return true;
}


